// ============================================================================================================================================
    //
    //
    //
    //
    // FNL 菲尼尔模块
    //
    //
    //
    //
    // ============================================================================================================================================
#ifndef UNITY_SHADER_DT_FNL_UTIL_INCLUDED  
#define UNITY_SHADER_DT_FNL_UTIL_INCLUDED
    // ==================================================================
    // 引用
    // ==================================================================
    //  #include "XXXXXX.hlsl"

    // ==================================================================
    // 私有函数
    // ==================================================================
    bool DTIsPerspectiveProjection()
    {
        return (unity_OrthoParams.w == 0);
    }
    void GetDot_N2V(float3 normalWS, float3 positionWS, inout float fnlvalue)
    { 
        if(DTIsPerspectiveProjection())//当是透视相机时
        {
        #if defined(DT_URP_MODE)
            float3 worldViewDir = GetWorldSpaceNormalizeViewDir(positionWS.xyz);
        #else
            float3 worldViewDir = normalize(_WorldSpaceCameraPos.xyz - positionWS.xyz);
        #endif
            fnlvalue = dot(normalWS.xyz, worldViewDir.xyz); 
        }
        else
        {
            float3 normalView = mul((float3x3)UNITY_MATRIX_V, normalWS).xyz;
            fnlvalue = clamp(normalView.z, -1.0, 1.0);             
        }
    }
    float DTOptimizeFnlSoft(float fnlvalue, float _Soft,float _Scale, float _Wide = 0.0)
    {
        #ifdef DT_USE_OPTIMIZE
            //Safe 安全约束
            float wide = max(0.001, 1.0 - _Wide);
            float soft = min(wide - 0.01,_Soft);
            //求值
            return smoothstep( soft, wide, fnlvalue) * _Scale;
        #else
            return pow(fnlvalue, _Soft * 10.0) * _Scale; 
        #endif
    }
    float DTFNL01(float fnlvalue)
    {
        return saturate(fnlvalue * 0.5 + 0.5);
    }
    float DTFNL010(float fnlvalue)
    {
        return saturate(1.0 - abs(fnlvalue));
    }
    // ==================================================================
    // 结构体
    // ==================================================================
   
    struct FresnelResult
    {
        float3 color;
        float value;
        float colBlend; // 0:add,1: mul
        float alpBlend; // 0:不影响，1：影响
    };
    FresnelResult initFresnelResult(float blend, float alpblend)
    {
        FresnelResult result = (FresnelResult)0;
        //安全计算
        result.colBlend = blend > 0 ? 1.0 : 0.0;
        result.alpBlend = alpblend > 0 ? 1.0 : 0.0;
        //安全计算
        result.alpBlend = 1.0 - result.alpBlend;
        result.color = float3(result.colBlend,result.colBlend,result.colBlend);            
        result.value = alpblend;
        return result;
    }    
    // ==================================================================
    // 计算函数
    // ==================================================================
    //0-1[反面到正面]
    FresnelResult CalcFresnelResult_Tex(int _IsOn, float3 _NormalWS,float3 _PositionWS, 
        float _Scale, float _Soft, float _ColBlend, float _Alpblend, float _Wide, float4 _FNLColor, float _IsFilp,sampler2D tex,float2 _uv)     
    {
        FresnelResult Result = initFresnelResult(_ColBlend,_Alpblend);
        if(_IsOn > 0.00001)
        {
            Result.color = _FNLColor.rgb * _FNLColor.a;
            float fnlvalue = 0;
            GetDot_N2V(_NormalWS,  _PositionWS, fnlvalue);
            fnlvalue =  DTFNL01(fnlvalue);
            fnlvalue = smoothstep( _Soft, 1.0, fnlvalue) ; 
            float2 _fnlUV = float2(fnlvalue, _uv.y );// + frac(float2(0.0,0.0) * float2(_Time.y,_Time.y));
            //从贴图获取 贴图取横向的U
            float4 texvalue = tex2D(tex, _fnlUV);
            texvalue = abs(_IsFilp - texvalue);
            Result.value = texvalue.a;
            Result.color = texvalue.rgb * Result.color;
        }
        return Result;
    }

    //0-1-0[反面到正面]
    FresnelResult CalcFresnelResult_F010(int _IsOn, float3 _NormalWS,float3 _PositionWS, 
        float _Scale, float _Soft, float _ColBlend, float _Alpblend, float _Wide, float4 _FNLColor, float _IsFilp)
    {
        FresnelResult Result = initFresnelResult(_ColBlend,_Alpblend); 
        if(_IsOn > 0.00001)
        {
            float _scale = _Scale;
            float _soft = _Soft;
            Result.color = _FNLColor.rgb * _FNLColor.a;
            float fnlvalue = 0;
            GetDot_N2V(_NormalWS, _PositionWS, fnlvalue);            
            //是否反相 
            fnlvalue = abs(_IsFilp - fnlvalue);
            //决定使用哪种显示模式，FULL：0->1 [反面到正面]，0-1-0[反面到正面]
            fnlvalue = DTFNL010(fnlvalue);
            //计算调节
            Result.value = DTOptimizeFnlSoft(fnlvalue,_Soft,_Scale, _Wide); 
        }
        return Result;
    }
    //0->1 [反面到正面]
    FresnelResult CalcFresnelResult_F01(int _IsOn, float3 _NormalWS,float3 _PositionWS, 
        float _Scale, float _Soft, float _ColBlend, float _Alpblend, float _Wide,float4 _FNLColor, float _IsFilp)
    {
        FresnelResult Result = initFresnelResult(_ColBlend,_Alpblend); 
        if(_IsOn > 0.00001)
        {
            float _scale = _Scale;
            float _soft = _Soft;
            Result.color = _FNLColor.rgb * _FNLColor.a;
            float fnlvalue = 0;
            GetDot_N2V(_NormalWS, _PositionWS, fnlvalue);

            //是否反相 
            fnlvalue = abs(_IsFilp -  fnlvalue);
            fnlvalue = saturate(fnlvalue * 0.5 + 0.5);
            fnlvalue = 1.0 - fnlvalue;
            //计算调节
            Result.value = DTOptimizeFnlSoft(fnlvalue, _Soft,_Scale, _Wide);
        }
        return Result;
    }


    FresnelResult CalcFresnelResult_Base(int _IsOn, float3 _NormalWS,float3 _PositionWS, 
        float _Scale, float _Soft, float _ColBlend, float _Alpblend,float4 _FNLColor, float _IsFilp, float _IsFull)
    {
        FresnelResult Result = initFresnelResult(_ColBlend,_Alpblend);
        if(_IsOn > 0.00001)
        {
            float _scale = _Scale;
            float _soft = _Soft;
            Result.color = _FNLColor.rgb * _FNLColor.a;
            float fnlvalue = 0;
            GetDot_N2V(_NormalWS, _PositionWS, fnlvalue);            
            //是否反相 
            fnlvalue = abs(_IsFilp - fnlvalue);            
            //决定使用哪种显示模式，FULL：0->1 [反面到正面]，0-1-0[反面到正面]
            float _IsFull = 0.0;
            fnlvalue = lerp(abs(fnlvalue),fnlvalue * 0.5 + 0.5, _IsFull);
            fnlvalue = saturate(1.0 - fnlvalue);

            //计算调节
            Result.value = DTOptimizeFnlSoft(fnlvalue,_Soft,_Scale); 
        }
        return Result;
    }
    // ==================================================================
    // 调用函数
    // ==================================================================
    void ApplyFresnelEffect(FresnelResult result, inout float3 color,inout float alpha)
    { 
        float3 c = lerp(color + result.color, color * result.color, result.colBlend);
        color = lerp(color, c, result.value);
        //小于0的颜色是不可控的。无特殊要求不允许颜色小于 0 
        color = max(0.0, color);
        //isAlp 不能小于0
        //isAlp = max(0.0, isAlp);
        alpha *= saturate(result.alpBlend + result.value); 
        //小于0或大于1的透明是不可控的。无特殊要求不允许透明溢出[0-1]的范围 
        alpha = max(0.0, alpha);
    }
#endif //UNITY_SHADER_DT_FNL_UTIL_INCLUDED